<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>easymybatis开发文档</title>
        <!-- 代码样式，可根据自己喜欢的改 -->
        <link rel="stylesheet" href="./static/highlight/styles/vs.css">
		<script src="./static/highlight/highlight.pack.js"></script>
		<script>hljs.initHighlightingOnLoad();</script>
        <link rel="stylesheet" type="text/css" href="./static/github2-rightpart.css" media="all">
        <link rel="stylesheet" type="text/css" href="./static/github1-contents.css">
        <link rel="stylesheet" href="./static/zTreeStyle.css" type="text/css">
        <style>
            .ztree li a.curSelectedNode {
                padding-top: 0px;
                background-color: #FFE6B0;
                color: black;
                height: 16px;
                border: 1px #FFB951 solid;
                opacity: 0.8;
            }
            .ztree{
                overflow: auto;
                height:100%;
                min-height: 200px;
                top: 0px;
            }
            .task-list{list-style-type: disc !important;}
        </style>
    </head>
    <body style="">
        <div>
            <div style="width:30%;">
                <ul id="tree" class="ztree" style="width: 260px; overflow: auto; position: fixed; z-index: 2147483647; border: 0px none; left: 0px; bottom: 0px;">
                <!-- 目录内容在网页另存为之后将插入到此处 -->
                </ul>
            </div>
            <div id="readme" style="width:70%;margin-left:25%;">
                <article class="markdown-body">


<!-- ***********************************************************内容分割线****************************************************************** -->
<!-- 请把你的html正文部分粘贴到此处，在浏览器中打开之后将会自动生成目录。如果想要将目录保留并嵌入到此文档中，只需在浏览器中“另存为->网页，全部”即可 -->
  <div class="ui container">
    <div id="project-title">
      <div class="title-wrap">
        <div class="left">
          <i class="icon eye"></i>
          文档预览:
          durcframework/easymybatis
        </div>
        <div class="right">
          Export by Gitee
        </div>
      </div>
    </div>

    <div class="ui container" id="wiki-preview-container">
      <div id="wiki-preview">
        <div class="ui segment">
          <div id="page-detail" class="markdown-body">
            <div class='title'>easymybatis开发文档</div><div class='content'><h1>
<a id="easymybatis开发文档" class="anchor" href="#easymybatis%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3"></a>easymybatis开发文档</h1>
<p>easymybatis是一个mybatis增强类库，目的为简化mybatis的开发，让开发更高效。</p>
<ul class="task-list">
<li>git地址：<a href="https://git.oschina.net/durcframework/easymybatis">easymybatis</a>
</li>
<li>demo地址：<a href="http://git.oschina.net/durcframework/easymybatis-springboot">demo with springboot</a>
</li>
<li>QQ交流群:328419269</li>
</ul>
<p>easymybatis的特性如下：</p>
<ul class="task-list">
<li>无需编写xml文件即可完成CRUD操作。</li>
<li>支持多表查询、聚合查询、分页查询（支持多种数据库）。</li>
<li>支持批量添加，指定字段批量添加。</li>
<li>支持Dao层访问控制，如某个dao只有查询功能，某个dao有crud功能等。</li>
<li>支持自定义sql，sql语句可以写在配置文件中，同样支持mybatis标签。</li>
<li>支持mysql，sqlserver，oracle，其它数据库扩展方便（增加一个模板文件即可）。</li>
<li>使用方式不变，与Spring集成只改了一处配置。</li>
<li>支持与springboot集成。</li>
<li>mybatis参数设置灵活，继承mybatis官方设置方式。</li>
<li>轻量级，无侵入性，可与传统mybatis用法共存。</li>
<li>没有修改框架源码(无插件)，可同时使用官方提供的功能。</li>
</ul>
<p>easymybatis支持的功能如下：</p>
<ul class="task-list">
<li>基本的CRUD</li>
<li>主键策略设置</li>
<li>字段填充功能</li>
<li>枚举属性</li>
<li>全局Dao</li>
<li>乐观锁</li>
<li>逻辑删除</li>
</ul>
<h2>
<a id="架构组成" class="anchor" href="#%E6%9E%B6%E6%9E%84%E7%BB%84%E6%88%90"></a>架构组成</h2>
<p>easymybatis的架构如下：</p>
<p><img src="https://git.oschina.net/uploads/images/2017/0905/135741_c7821a5b_332975.png" alt="架构" title="em_arc.png"></p>
<h2>
<a id="运行流程" class="anchor" href="#%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B"></a>运行流程</h2>
<p>easymybatis的运行流程图：</p>
<p><img src="https://git.oschina.net/uploads/images/2017/0905/135821_508ba7cc_332975.png" alt="运行流程" title="em_flow.png"></p>
<ol class="task-list">
<li>服务器启动的时候easymybatis负责扫描Dao.java。</li>
<li>扫描完成后解析出Dao.class以及实体类Entity.class。</li>
<li>代码生成组件根据Dao.class和Entity.class生成mapper文件内容，生成方式由velocity模板指定。</li>
<li>把mapper文件内容转化成Resource对象设置到SqlSessionFactory中。</li>
</ol>
<h1>
<a id="快速开始" class="anchor" href="#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B"></a>快速开始</h1>
<h2>
<a id="创建springboot项目" class="anchor" href="#%E5%88%9B%E5%BB%BAspringboot%E9%A1%B9%E7%9B%AE"></a>创建springboot项目</h2>
<p>访问<a href="http://start.spring.io/">http://start.spring.io/</a> 生成一个springboot空项目，输入Group，Artifact点生成即可，如图：
<img src="https://gitee.com/uploads/images/2017/1219/121354_be6dc10c_332975.png" alt="创建空项目" title="1.png">
点击Generate Project，下载demo.zip</p>
<h2>
<a id="导入项目" class="anchor" href="#%E5%AF%BC%E5%85%A5%E9%A1%B9%E7%9B%AE"></a>导入项目</h2>
<p>将下载的demo.zip解压，然后导入项目。eclipse中右键 -&gt; Import... -&gt; Existing Maven Project，选择项目文件夹。导入到eclipse中后等待maven相关jar包下载。</p>
<h2>
<a id="添加maven依赖" class="anchor" href="#%E6%B7%BB%E5%8A%A0maven%E4%BE%9D%E8%B5%96"></a>添加maven依赖</h2>
<p>jar包下载完成后，打开pom.xml，添加如下依赖：</p>
<div class="white"><div class="highlight"><pre><span class="c">&lt;!-- easymybatis的starter --&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>net.oschina.durcframework<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>easymybatis-spring-boot-starter<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>1.4.5<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>org.springframework.boot<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>spring-boot-starter-web<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
<span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>mysql<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>mysql-connector-java<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;scope&gt;</span>runtime<span class="nt">&lt;/scope&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</pre></div></div>
<h2>
<a id="添加数据库配置" class="anchor" href="#%E6%B7%BB%E5%8A%A0%E6%95%B0%E6%8D%AE%E5%BA%93%E9%85%8D%E7%BD%AE"></a>添加数据库配置</h2>
<p>在application.properties中添加数据库配置</p>
<div class="white"><div class="highlight"><pre>spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/stu?useUnicode=true&amp;characterEncoding=utf-8&amp;zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=root
</pre></div></div>
<h2>
<a id="添加java文件" class="anchor" href="#%E6%B7%BB%E5%8A%A0java%E6%96%87%E4%BB%B6"></a>添加Java文件</h2>
<p>假设数据库中有张t_user表，DDL如下：</p>
<div class="white"><div class="highlight"><pre><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="nv">`t_user`</span> <span class="p">(</span>
  <span class="nv">`id`</span> <span class="n">int</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span> <span class="k">NOT</span> <span class="k">NULL</span> <span class="n">AUTO_INCREMENT</span> <span class="k">COMMENT</span> <span class="s1">'ID'</span><span class="p">,</span>
  <span class="nv">`username`</span> <span class="n">varchar</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span> <span class="k">DEFAULT</span> <span class="k">NULL</span> <span class="k">COMMENT</span> <span class="s1">'用户名'</span><span class="p">,</span>
  <span class="nv">`state`</span> <span class="n">tinyint</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="k">DEFAULT</span> <span class="k">NULL</span> <span class="k">COMMENT</span> <span class="s1">'状态'</span><span class="p">,</span>
  <span class="nv">`isdel`</span> <span class="n">bit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">DEFAULT</span> <span class="k">NULL</span> <span class="k">COMMENT</span> <span class="s1">'是否删除'</span><span class="p">,</span>
  <span class="nv">`remark`</span> <span class="n">text</span> <span class="k">COMMENT</span> <span class="s1">'备注'</span><span class="p">,</span>
  <span class="nv">`add_time`</span> <span class="n">datetime</span> <span class="k">DEFAULT</span> <span class="k">NULL</span> <span class="k">COMMENT</span> <span class="s1">'添加时间'</span><span class="p">,</span>
  <span class="k">PRIMARY</span> <span class="k">KEY</span> <span class="p">(</span><span class="nv">`id`</span><span class="p">)</span>
<span class="p">)</span> <span class="n">ENGINE</span><span class="o">=</span><span class="n">InnoDB</span> <span class="k">DEFAULT</span> <span class="n">CHARSET</span><span class="o">=</span><span class="n">utf8</span> <span class="k">COMMENT</span><span class="o">=</span><span class="s1">'用户表'</span><span class="p">;</span>
</pre></div></div>
<p>我们加入对应的实体类和Dao:</p>
<ul class="task-list">
<li>TUser.java ：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="nd">@Table</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"t_user"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">TUser</span> <span class="o">{</span> 
    <span class="nd">@Id</span>
    <span class="nd">@Column</span><span class="o">(</span><span class="n">name</span><span class="o">=</span><span class="s">"id"</span><span class="o">)</span>
    <span class="nd">@GeneratedValue</span><span class="o">(</span><span class="n">strategy</span> <span class="o">=</span> <span class="n">GenerationType</span><span class="o">.</span><span class="na">IDENTITY</span><span class="o">)</span>
    <span class="kd">private</span> <span class="n">Integer</span> <span class="n">id</span><span class="o">;</span>    <span class="c1">// ID  </span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">username</span><span class="o">;</span> <span class="c1">// 用户名   </span>
    <span class="kd">private</span> <span class="n">Byte</span> <span class="n">state</span><span class="o">;</span>    <span class="c1">// 状态  </span>
    <span class="kd">private</span> <span class="n">Boolean</span> <span class="n">isdel</span><span class="o">;</span> <span class="c1">// 是否删除    </span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">remark</span><span class="o">;</span> <span class="c1">// 备注  </span>
    <span class="kd">private</span> <span class="n">Date</span> <span class="n">addTime</span><span class="o">;</span>  <span class="c1">// 添加时间</span>
    
    <span class="c1">// 省略 getter setter</span>
<span class="o">}</span>
</pre></div></div>
<p>实体类文件采用和hibernate相同的方式，您可以使用我们的代码生成工具生成
<a href="https://gitee.com/durcframework/easymybatis-generator">https://gitee.com/durcframework/easymybatis-generator</a></p>
<ul class="task-list">
<li>TUserDao.java :</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">TUserDao</span> <span class="kd">extends</span> <span class="n">CrudDao</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="o">{</span>
<span class="o">}</span>
</pre></div></div>
<p>TUserDao继承CrudDao即可，这样这个Dao就拥有了CRUD功能。</p>
<h2>
<a id="添加测试用例" class="anchor" href="#%E6%B7%BB%E5%8A%A0%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B"></a>添加测试用例</h2>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">TUserDaoTest</span> <span class="kd">extends</span> <span class="n">DemoApplicationTests</span> <span class="o">{</span>

    <span class="nd">@Autowired</span>
    <span class="n">TUserDao</span> <span class="n">dao</span><span class="o">;</span>

        <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testInsert</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="n">TUser</span><span class="o">();</span>
        <span class="n">user</span><span class="o">.</span><span class="na">setIsdel</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>       
        <span class="n">user</span><span class="o">.</span><span class="na">setRemark</span><span class="o">(</span><span class="s">"testInsert"</span><span class="o">);</span>        
        <span class="n">user</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="s">"张三"</span><span class="o">);</span>
        
        <span class="n">dao</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
        
        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"添加后的主键:"</span> <span class="o">+</span> <span class="n">user</span><span class="o">.</span><span class="na">getId</span><span class="o">());</span>        
    <span class="o">}</span>
    
    <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testGet</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>                
    <span class="o">}</span>

        <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testUpdate</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="n">user</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="s">"李四"</span><span class="o">);</span>      
        <span class="n">user</span><span class="o">.</span><span class="na">setIsdel</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
        
        <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"testUpdate --&gt; "</span> <span class="o">+</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>

        <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testDel</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="n">TUser</span><span class="o">();</span>
        <span class="n">user</span><span class="o">.</span><span class="na">setId</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">del</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
        <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"del --&gt; "</span> <span class="o">+</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div></div>
<p>然后运行单元测试，运行成功后表示项目已经搭建完毕了。</p>
<p>最后项目结构图：</p>
<p><img src="https://git.oschina.net/uploads/images/2017/1012/112354_8c2c6969_332975.png" alt="最后项目结构图" title="2.png"></p>
<h1>
<a id="查询" class="anchor" href="#%E6%9F%A5%E8%AF%A2"></a>查询</h1>
<p>本小节主要讲解easymybatis的查询功能。easymybatis提供丰富的查询方式，满足日常查询所需。</p>
<h2>
<a id="分页查询" class="anchor" href="#%E5%88%86%E9%A1%B5%E6%9F%A5%E8%AF%A2"></a>分页查询</h2>
<h3>
<a id="方式1" class="anchor" href="#%E6%96%B9%E5%BC%8F1"></a>方式1</h3>
<p>前端传递两个分页参数pageIndex，pageSize</p>
<div class="white"><div class="highlight"><pre> <span class="c1">// http://localhost:8080/page1?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page1"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page1</span><span class="o">(</span><span class="kt">int</span> <span class="n">pageIndex</span><span class="o">,</span><span class="kt">int</span> <span class="n">pageSize</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">setPage</span><span class="o">(</span><span class="n">pageIndex</span><span class="o">,</span> <span class="n">pageSize</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="方式2" class="anchor" href="#%E6%96%B9%E5%BC%8F2"></a>方式2</h3>
<p>PageParam里面封装了pageIndex，pageSize参数</p>
<div class="white"><div class="highlight"><pre> <span class="c1">// http://localhost:8080/page2?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page2"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page2</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="返回结果集和总记录数" class="anchor" href="#%E8%BF%94%E5%9B%9E%E7%BB%93%E6%9E%9C%E9%9B%86%E5%92%8C%E6%80%BB%E8%AE%B0%E5%BD%95%E6%95%B0"></a>返回结果集和总记录数</h3>
<p>方式1和方式2只能查询结果集，通常我们查询还需返回记录总数并返回给前端，easymybatis的处理方式如下：</p>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/page3?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page3"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">&gt;</span> <span class="nf">page3</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="kt">long</span> <span class="n">total</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">countTotal</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        
        <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">&gt;();</span>
        <span class="n">result</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"list"</span><span class="o">,</span> <span class="n">list</span><span class="o">);</span>
        <span class="n">result</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"total"</span><span class="o">,</span> <span class="n">total</span><span class="o">);</span>
        
        <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<p>easymybatis提供一种更简洁的方式来处理：</p>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/page4?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page4"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">PageInfo</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page4</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">PageInfo</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">QueryUtils</span><span class="o">.</span><span class="na">query</span><span class="o">(</span><span class="n">dao</span><span class="o">,</span> <span class="n">param</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<p>PageInfo里面包含了List，total信息，还包含了一些额外信息，完整数据如下：</p>
<div class="white"><div class="highlight"><pre><span class="p">{</span><span class="w">
    </span><span class="s2">"currentPageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">当前页</span><span class="w">
    </span><span class="s2">"firstPageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">首页</span><span class="w">
    </span><span class="s2">"lastPageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">尾页</span><span class="w">
    </span><span class="s2">"list"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">     </span><span class="err">//</span><span class="w"> </span><span class="err">结果集</span><span class="w">
        </span><span class="p">{},</span><span class="w">
        </span><span class="p">{}</span><span class="w">
    </span><span class="p">],</span><span class="w">
    </span><span class="s2">"nextPageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">下一页</span><span class="w">
    </span><span class="s2">"pageCount"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">总页数</span><span class="w">
    </span><span class="s2">"pageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">当前页</span><span class="w">
    </span><span class="s2">"pageSize"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">每页记录数</span><span class="w">
    </span><span class="s2">"prePageIndex"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">上一页</span><span class="w">
    </span><span class="s2">"start"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
    </span><span class="s2">"total"</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="w"> </span><span class="err">//</span><span class="w"> </span><span class="err">总记录数</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></pre></div></div>
<h3>
<a id="完整代码" class="anchor" href="#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81"></a>完整代码</h3>
<div class="white"><div class="highlight"><pre><span class="nd">@RestController</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserSchController</span> <span class="o">{</span>

    <span class="nd">@Autowired</span>
    <span class="kd">private</span> <span class="n">TUserDao</span> <span class="n">dao</span><span class="o">;</span>
    
    <span class="c1">// http://localhost:8080/page1?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page1"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page1</span><span class="o">(</span><span class="kt">int</span> <span class="n">pageIndex</span><span class="o">,</span><span class="kt">int</span> <span class="n">pageSize</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">setPage</span><span class="o">(</span><span class="n">pageIndex</span><span class="o">,</span> <span class="n">pageSize</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
    
    <span class="c1">// http://localhost:8080/page2?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page2"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page2</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
    
    <span class="c1">// http://localhost:8080/page3?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page3"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">&gt;</span> <span class="nf">page3</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="kt">long</span> <span class="n">total</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">countTotal</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        
        <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span><span class="n">Object</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">&gt;();</span>
        <span class="n">result</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"list"</span><span class="o">,</span> <span class="n">list</span><span class="o">);</span>
        <span class="n">result</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"total"</span><span class="o">,</span> <span class="n">total</span><span class="o">);</span>
        
        <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
    <span class="o">}</span>
    
    <span class="c1">// http://localhost:8080/page4?pageIndex=1&amp;pageSize=10</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"page4"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">PageInfo</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">page4</span><span class="o">(</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">PageInfo</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">QueryUtils</span><span class="o">.</span><span class="na">query</span><span class="o">(</span><span class="n">dao</span><span class="o">,</span> <span class="n">param</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">result</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div></div>
<h2>
<a id="根据参数字段查询" class="anchor" href="#%E6%A0%B9%E6%8D%AE%E5%8F%82%E6%95%B0%E5%AD%97%E6%AE%B5%E6%9F%A5%E8%AF%A2"></a>根据参数字段查询</h2>
<h3>
<a id="查询姓名为张三的用户" class="anchor" href="#%E6%9F%A5%E8%AF%A2%E5%A7%93%E5%90%8D%E4%B8%BA%E5%BC%A0%E4%B8%89%E7%9A%84%E7%94%A8%E6%88%B7"></a>查询姓名为张三的用户</h3>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/sch?username=张三</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"sch"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">sch</span><span class="o">(</span><span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="查询姓名为张三并且拥有的钱大于100块" class="anchor" href="#%E6%9F%A5%E8%AF%A2%E5%A7%93%E5%90%8D%E4%B8%BA%E5%BC%A0%E4%B8%89%E5%B9%B6%E4%B8%94%E6%8B%A5%E6%9C%89%E7%9A%84%E9%92%B1%E5%A4%A7%E4%BA%8E100%E5%9D%97"></a>查询姓名为张三并且拥有的钱大于100块</h3>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/sch2?username=张三</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"sch2"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">sch2</span><span class="o">(</span><span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">username</span><span class="o">).</span><span class="na">gt</span><span class="o">(</span><span class="s">"money"</span><span class="o">,</span> <span class="mi">100</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="查询姓名为张三并带分页" class="anchor" href="#%E6%9F%A5%E8%AF%A2%E5%A7%93%E5%90%8D%E4%B8%BA%E5%BC%A0%E4%B8%89%E5%B9%B6%E5%B8%A6%E5%88%86%E9%A1%B5"></a>查询姓名为张三并带分页</h3>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/sch3?username=张三&amp;pageIndex=1&amp;pageSize=5</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"sch3"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">sch3</span><span class="o">(</span><span class="n">String</span> <span class="n">username</span><span class="o">,</span><span class="n">PageParam</span> <span class="n">param</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="查询钱最多的前三名" class="anchor" href="#%E6%9F%A5%E8%AF%A2%E9%92%B1%E6%9C%80%E5%A4%9A%E7%9A%84%E5%89%8D%E4%B8%89%E5%90%8D"></a>查询钱最多的前三名</h3>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/sch4</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"sch4"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">sch4</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">addSort</span><span class="o">(</span><span class="s">"money"</span><span class="o">,</span> <span class="n">Sort</span><span class="o">.</span><span class="na">DESC</span><span class="o">)</span> <span class="c1">// 按金额降序</span>
            <span class="o">.</span><span class="na">setPage</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">3</span><span class="o">);</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<h3>
<a id="将参数放在对象中查询" class="anchor" href="#%E5%B0%86%E5%8F%82%E6%95%B0%E6%94%BE%E5%9C%A8%E5%AF%B9%E8%B1%A1%E4%B8%AD%E6%9F%A5%E8%AF%A2"></a>将参数放在对象中查询</h3>
<div class="white"><div class="highlight"><pre><span class="c1">// http://localhost:8080/sch5?username=张三</span>
    <span class="nd">@GetMapping</span><span class="o">(</span><span class="s">"sch5"</span><span class="o">)</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="nf">sch5</span><span class="o">(</span><span class="n">UserParam</span> <span class="n">userParam</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">userParam</span><span class="o">.</span><span class="na">toQuery</span><span class="o">();</span>
        <span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span> <span class="n">userParam</span><span class="o">.</span><span class="na">getUsername</span><span class="o">());</span>
        <span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<p>UserParam继承PageSortParam类，表示支持分页和排序查询</p>
<h3>
<a id="使用普通bean查询" class="anchor" href="#%E4%BD%BF%E7%94%A8%E6%99%AE%E9%80%9Abean%E6%9F%A5%E8%AF%A2"></a>使用普通bean查询</h3>
<p>假设有个User类如下</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">User</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="n">Integer</span> <span class="n">id</span><span class="o">;</span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">userName</span><span class="o">;</span>

    <span class="kd">public</span> <span class="n">Integer</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">id</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setId</span><span class="o">(</span><span class="n">Integer</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getUserName</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">userName</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setUserName</span><span class="o">(</span><span class="n">String</span> <span class="n">userName</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">userName</span> <span class="o">=</span> <span class="n">userName</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div></div>
<p>我们将这个类作为查询参数,那么在springmvc中可以这样写:</p>
<div class="white"><div class="highlight"><pre><span class="nd">@GetMapping</span><span class="o">(</span><span class="n">path</span><span class="o">=</span><span class="s">"findUserBean.do"</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="nf">findUser</span><span class="o">(</span><span class="n">User</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="n">Query</span><span class="o">.</span><span class="na">buildFromBean</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
    <span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
    <span class="k">return</span> <span class="n">list</span><span class="o">;</span>
<span class="o">}</span>
</pre></div></div>
<p>Query query = Query.buildFromBean(user);这句是将User中的属性转换成对应条件,假设userName的值为"jim",那么会封装成一个条件where user_name='jim'</p>
<p>浏览器输入链接:<a href="http://localhost:8080/easymybatis-springmvc/findUserBean.do?userName=jim">http://localhost:8080/easymybatis-springmvc/findUserBean.do?userName=jim</a>
后台将会执行如下SQL:</p>
<div class="white"><div class="highlight"><pre>SELECT id,user_name FROM user t WHERE t.user_name = ?
</pre></div></div>
<p>?的值为jim</p>
<h3>
<a id="condition注解" class="anchor" href="#condition%E6%B3%A8%E8%A7%A3"></a>@Condition注解</h3>
<p>@Condition注解用来强化查询，有了这个注解可以生成各种查询条件。</p>
<p>@Condition注解有三个属性：</p>
<ul class="task-list">
<li>joint：表达式之间的连接符,AND|OR,默认AND</li>
<li>column：数据库字段名，可选</li>
<li>operator：连接符枚举，存放了等于、大于、小于等连接符</li>
</ul>
<p>如果要查询id大于2的用户只需在get方法上加上一个@Condition注解即可:</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Condition</span><span class="o">(</span><span class="n">operator</span><span class="o">=</span><span class="n">Operator</span><span class="o">.</span><span class="na">gt</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">Integer</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">id</span><span class="o">;</span>
<span class="o">}</span>
</pre></div></div>
<p>这样，当id有值时，会封装成一个<strong>where id&gt;2</strong>的条件</p>
<ul class="task-list">
<li>需要注意的是，如果不指定column属性，系统会默认取get方法中属性名，然后转换成数据库字段名。如果需要指定数据库字段名的话，可以使用@Condition的column属性。</li>
</ul>
<p>public Integer get++UserName++() {
return this.userName;
}</p>
<p>这种情况下会取下划线部分字段，然后转换成数据库字段名。</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Condition</span><span class="o">(</span><span class="n">column</span><span class="o">=</span><span class="s">"username"</span><span class="o">)</span> <span class="c1">// 显示指定字段名</span>
<span class="kd">public</span> <span class="n">Integer</span> <span class="nf">getUserName</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">userName</span><span class="o">;</span>
<span class="o">}</span>
</pre></div></div>
<p>使用@Condition可以生产更加灵活的条件查询,比如需要查询日期为2017-12-1~2017-12-10日的记录,我们可以这样写:</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Condition</span><span class="o">(</span><span class="n">column</span><span class="o">=</span><span class="s">"add_date"</span><span class="o">,</span><span class="n">operator</span><span class="o">=</span><span class="n">Operator</span><span class="o">.</span><span class="na">ge</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">Date</span> <span class="nf">getStartDate</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">startDate</span><span class="o">;</span>
<span class="o">}</span>

<span class="nd">@Condition</span><span class="o">(</span><span class="n">column</span><span class="o">=</span><span class="s">"add_date"</span><span class="o">,</span><span class="n">operator</span><span class="o">=</span><span class="n">Operator</span><span class="o">.</span><span class="na">lt</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">Date</span> <span class="nf">getEndDate</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">endDate</span><span class="o">;</span>
<span class="o">}</span>
</pre></div></div>
<p>转换成SQL语句:</p>
<div class="white"><div class="highlight"><pre>t.add_date&gt;='2017-12-1' AND t.add_date&lt;'2017-12-10'
</pre></div></div>
<h4>
<a id="in查询" class="anchor" href="#in%E6%9F%A5%E8%AF%A2"></a>IN查询</h4>
<p>假设前端页面传来多个值比如checkbox勾选多个id=[1,2],那么我们在User类里面可以用Integer[]或List来接收.</p>
<div class="white"><div class="highlight"><pre><span class="kd">private</span> <span class="n">Integer</span><span class="o">[]</span> <span class="n">idArr</span><span class="o">;</span>

<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setIdArr</span><span class="o">(</span><span class="n">Integer</span><span class="o">[]</span> <span class="n">idArr</span><span class="o">)</span> <span class="o">{</span><span class="k">this</span><span class="o">.</span><span class="na">idArr</span> <span class="o">=</span> <span class="n">idArr</span><span class="o">;}</span>

<span class="nd">@Condition</span><span class="o">(</span><span class="n">column</span><span class="o">=</span><span class="s">"id"</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">Integer</span><span class="o">[]</span> <span class="nf">getIdArr</span><span class="o">()</span> <span class="o">{</span><span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">idArr</span><span class="o">;}</span>
</pre></div></div>
<p>这样会生成where id IN(1,2)条件。</p>
<h2>
<a id="排序查询" class="anchor" href="#%E6%8E%92%E5%BA%8F%E6%9F%A5%E8%AF%A2"></a>排序查询</h2>
<p>// 根据添加时间倒序</p>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">addSort</span><span class="o">(</span><span class="s">"create_time"</span><span class="o">,</span><span class="n">Sort</span><span class="o">.</span><span class="na">DESC</span><span class="o">);</span>
<span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<h2>
<a id="多表关联查询" class="anchor" href="#%E5%A4%9A%E8%A1%A8%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2"></a>多表关联查询</h2>
<p>多表关联查询使用的地方很多，比如需要关联第二张表，获取第二张表的几个字段，然后返回给前端。</p>
<p>easymybatis的用法如下：
假如我们需要关联第二张表，并且获取第二张表里的city，address字段。步骤如下：</p>
<ul class="task-list">
<li>在实体类中添加city，address字段，并标记@Transient注解。只要不是主表中的字段都要加上@Transient</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="nd">@Transient</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">city</span><span class="o">;</span>
<span class="nd">@Transient</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">address</span><span class="o">;</span>

<span class="c1">// getter setter</span>
</pre></div></div>
<ul class="task-list">
<li>接下来是查询代码：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="c1">// 添加第二张表的字段,跟主表字段一起返回</span>
<span class="n">query</span><span class="o">.</span><span class="na">addOtherColumns</span><span class="o">(</span>
    <span class="s">"t2.city"</span>
    <span class="o">,</span><span class="s">"t2.address"</span>
<span class="o">);</span>
<span class="c1">// 左连接查询,主表的alias默认为t</span>
<span class="n">query</span><span class="o">.</span><span class="na">join</span><span class="o">(</span><span class="s">"LEFT JOIN user_info t2 ON t.id = t2.user_id"</span><span class="o">);</span> 
<span class="c1">// 添加查询条件</span>
<span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"t.username"</span><span class="o">,</span> <span class="s">"张三"</span><span class="o">);</span>

<span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<p>得到的SQL语句：</p>
<div class="white"><div class="highlight"><pre><span class="k">SELECT</span> 
    <span class="n">t</span><span class="p">.</span><span class="nv">`id`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`username`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`state`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`isdel`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`remark`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`add_time`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`money`</span> <span class="p">,</span> <span class="n">t</span><span class="p">.</span><span class="nv">`left_money`</span> 
    <span class="p">,</span> <span class="n">t2</span><span class="p">.</span><span class="n">city</span> <span class="p">,</span> <span class="n">t2</span><span class="p">.</span><span class="n">address</span> 
<span class="k">FROM</span> <span class="nv">`t_user`</span> <span class="n">t</span> <span class="k">LEFT</span> <span class="k">JOIN</span> <span class="n">user_info</span> <span class="n">t2</span> <span class="k">ON</span> <span class="n">t</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">t2</span><span class="p">.</span><span class="n">user_id</span> 
<span class="k">WHERE</span> <span class="n">t</span><span class="p">.</span><span class="n">username</span> <span class="o">=</span> <span class="o">?</span>
<span class="k">LIMIT</span> <span class="o">?</span><span class="p">,</span><span class="o">?</span>
</pre></div></div>
<p>关联了user_info表之后，还可以筛选user_info的数据，也就是针对user_info表进行查询：</p>
<div class="white"><div class="highlight"><pre><span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"t2.city"</span><span class="o">,</span><span class="s">"杭州"</span><span class="o">);</span>
</pre></div></div>
<h2>
<a id="使用select查询" class="anchor" href="#%E4%BD%BF%E7%94%A8select%E6%9F%A5%E8%AF%A2"></a>使用@Select查询</h2>
<p>@Select注解是mybatis官方提供的一个功能，easymybatis可以理解为是官方的一种扩展，因此同样支持此功能。
在Dao中添加如下代码：</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Select</span><span class="o">(</span><span class="s">"select * from t_user where id=#{id}"</span><span class="o">)</span>
<span class="n">TUser</span> <span class="nf">selectById</span><span class="o">(</span><span class="nd">@Param</span><span class="o">(</span><span class="s">"id"</span><span class="o">)</span> <span class="kt">int</span> <span class="n">id</span><span class="o">);</span>
</pre></div></div>
<p>编写测试用例</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Test</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">testSelectById</span><span class="o">()</span> <span class="o">{</span>
    <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">selectById</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>

    <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUsername</span><span class="o">());</span>
<span class="o">}</span>
</pre></div></div>
<p>除了@Select之外，还有@Update，@Insert，@Delete，这里就不多做演示了。</p>
<h2>
<a id="query类详解" class="anchor" href="#query%E7%B1%BB%E8%AF%A6%E8%A7%A3"></a>Query类详解</h2>
<p>Query是一个查询参数类，通常配合Dao一起使用。</p>
<h3>
<a id="参数介绍" class="anchor" href="#%E5%8F%82%E6%95%B0%E4%BB%8B%E7%BB%8D"></a>参数介绍</h3>
<p>Query里面封装了一系列查询参数，主要分为以下几类：</p>
<ul class="task-list">
<li>分页参数：设置分页</li>
<li>排序参数：设置排序字段</li>
<li>条件参数：设置查询条件</li>
<li>字段参数：可返回指定字段</li>
</ul>
<p>下面逐个讲解每个参数的用法。</p>
<h3>
<a id="分页参数" class="anchor" href="#%E5%88%86%E9%A1%B5%E5%8F%82%E6%95%B0"></a>分页参数</h3>
<p>一般来说分页的使用比较简单，通常是两个参数，
pageIndex：当前页索引，pageSize：每页几条数据。
Query类使用**setPage(pageIdnex, pageSize)**方法来设置。
假如我们要查询第二页，每页10条数据，代码可以这样写：</p>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">setPage</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="mi">10</span><span class="o">);</span>
<span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<p>如果要实现不规则分页，可以这样写：</p>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">setStart</span><span class="o">(</span><span class="mi">3</span><span class="o">).</span><span class="na">setLimit</span><span class="o">(</span><span class="mi">5</span><span class="o">);</span>
<span class="c1">// 对应mysql：limit 3,5</span>
</pre></div></div>
<ul class="task-list">
<li>如果要查询所有数据,则可以这样写:</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">setQueryAll</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<h3>
<a id="排序参数" class="anchor" href="#%E6%8E%92%E5%BA%8F%E5%8F%82%E6%95%B0"></a>排序参数</h3>
<p>设置排序，有两个方法：</p>
<div class="white"><div class="highlight"><pre>addSort(String sortname)
addSort(String sortname, Sort sort)
</pre></div></div>
<p>其中sortname为数据库字段，非javaBean属性</p>
<ul class="task-list">
<li>addSort(String sortname) 添加排序字段，默认使用ASC</li>
<li>addSort(String sortname, Sort sort)则可以指定排序方式，Sort为排序方式枚举
假如要按照添加时间倒序，可以这样写：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">addSort</span><span class="o">(</span><span class="s">"create_time"</span><span class="o">,</span><span class="n">Sort</span><span class="o">.</span><span class="na">DESC</span><span class="o">);</span>
<span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<p>添加多个排序字段可以在后面追加：</p>
<div class="white"><div class="highlight"><pre>query.addSort("create_time",Sort.DESC).addSort("id",Sort.ASC);
</pre></div></div>
<h3>
<a id="条件参数" class="anchor" href="#%E6%9D%A1%E4%BB%B6%E5%8F%82%E6%95%B0"></a>条件参数</h3>
<p>条件参数是用的最多一个，因为在查询中往往需要加入各种条件。
easymybatis在条件查询上面做了一些封装，这里不做太多讲解，只讲下基本的用法，以后会单独开一篇文章来介绍。感兴趣的同学可以自行查看源码，也不难理解。</p>
<p>条件参数使用非常简单，Query对象封装一系列常用条件查询。</p>
<ul class="task-list">
<li>等值查询eq(String columnName, Object value)，columnName为数据库字段名，value为查询的值
假设我们要查询姓名为张三的用户，可以这样写：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"username"</span><span class="o">,</span><span class="s">"张三"</span><span class="o">);</span>
<span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<p>通过方法名即可知道eq表示等于'='，同理lt表示小于&lt;,gt表示大于&gt;</p>
<table>
<thead>
<tr>
<th>查询方式</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>eq</td>
<td>等于=</td>
</tr>
<tr>
<td>gt</td>
<td>大于&gt;</td>
</tr>
<tr>
<td>lt</td>
<td>小于&lt;</td>
</tr>
<tr>
<td>ge</td>
<td>大于等于&gt;=</td>
</tr>
<tr>
<td>le</td>
<td>小于等于&lt;=</td>
</tr>
<tr>
<td>notEq</td>
<td>不等于&lt;&gt;</td>
</tr>
<tr>
<td>like</td>
<td>模糊查询</td>
</tr>
<tr>
<td>in</td>
<td>in()查询</td>
</tr>
<tr>
<td>notIn</td>
<td>not in()查询</td>
</tr>
<tr>
<td>isNull</td>
<td>NULL值查询</td>
</tr>
<tr>
<td>notNull</td>
<td>IS NOT NULL</td>
</tr>
<tr>
<td>notEmpty</td>
<td>字段不为空，非NULL且有内容</td>
</tr>
<tr>
<td>isEmpty</td>
<td>字段为NULL或者为''</td>
</tr>
</tbody>
</table>
<p>如果上述方法还不能满足查询需求的话，我们可以使用自定sql的方式来编写查询条件，方法为：</p>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="n">query</span><span class="o">.</span><span class="na">sql</span><span class="o">(</span><span class="s">" username='Jim' OR username='Tom'"</span><span class="o">);</span>
</pre></div></div>
<p><strong>注意</strong>：sql()方法不会处理sql注入问题，因此尽量少用。</p>
<h3>
<a id="字段参数" class="anchor" href="#%E5%AD%97%E6%AE%B5%E5%8F%82%E6%95%B0"></a>字段参数</h3>
<p>在某些场景下，我们只想获取表里面几个字段的信息，不想查询所有字段。此时使用方式如下：</p>
<div class="white"><div class="highlight"><pre><span class="n">Query</span> <span class="n">query</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Query</span><span class="o">();</span>
<span class="c1">// 只返回id,username</span>
<span class="n">query</span><span class="o">.</span><span class="na">setColumns</span><span class="o">(</span><span class="n">Arrays</span><span class="o">.</span><span class="na">asList</span><span class="o">(</span><span class="s">"id"</span><span class="o">,</span><span class="s">"username"</span><span class="o">));</span>
<span class="n">List</span><span class="o">&lt;</span><span class="n">TUser</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>
</pre></div></div>
<p>这里的"id"，"username"都为数据库字段。</p>
<h1>
<a id="主键策略设置" class="anchor" href="#%E4%B8%BB%E9%94%AE%E7%AD%96%E7%95%A5%E8%AE%BE%E7%BD%AE"></a>主键策略设置</h1>
<p>跟hibernate的主键生成策略一致</p>
<h2>
<a id="主键自增" class="anchor" href="#%E4%B8%BB%E9%94%AE%E8%87%AA%E5%A2%9E"></a>主键自增</h2>
<p>数据库主键设置自增后，这样设置：</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Id</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"id"</span><span class="o">)</span>
<span class="nd">@GeneratedValue</span><span class="o">(</span><span class="n">strategy</span> <span class="o">=</span> <span class="n">GenerationType</span><span class="o">.</span><span class="na">IDENTITY</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">Integer</span> <span class="n">id</span><span class="o">;</span>
</pre></div></div>
<p>这样在做insert后，id会自动填充自增后的值。</p>
<h2>
<a id="主键使用uuid" class="anchor" href="#%E4%B8%BB%E9%94%AE%E4%BD%BF%E7%94%A8uuid"></a>主键使用uuid</h2>
<p>数据库主键是varchar类型，insert后自动填充uuid，并返回。</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Id</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"id"</span><span class="o">)</span>
<span class="nd">@GeneratedValue</span><span class="o">(</span><span class="n">generator</span> <span class="o">=</span> <span class="s">"system-uuid"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">id</span><span class="o">;</span>
</pre></div></div>
<p>这样在做insert后，id字段会自动填充uuid。</p>
<ul class="task-list">
<li>注：uuid的生成方式是调用数据库底层实现，如MySql的实现方式为： SELECT UUID()</li>
</ul>
<h2>
<a id="自定义uuid" class="anchor" href="#%E8%87%AA%E5%AE%9A%E4%B9%89uuid"></a>自定义uuid</h2>
<p>如果不希望使用底层数据库的uuid，可自定义自己实现，实现方式如下：</p>
<ul class="task-list">
<li>首先entity中的id字段@GeneratedValue注解设置成AUTO</li>
</ul>
<div class="white"><div class="highlight"><pre>@Id
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.AUTO)
private String id;
</pre></div></div>
<ul class="task-list">
<li>创建一个类UUIDFill并继承FillHandler类</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UUIDFill</span> <span class="kd">extends</span> <span class="n">FillHandler</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getColumnName</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"id"</span><span class="o">;</span> <span class="c1">// 作用在id字段上</span>
    <span class="o">}</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">FillType</span> <span class="nf">getFillType</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">FillType</span><span class="o">.</span><span class="na">INSERT</span><span class="o">;</span> <span class="c1">// INSERT时触发</span>
    <span class="o">}</span>
    <span class="nd">@Override</span>
    <span class="kd">protected</span> <span class="n">Object</span> <span class="nf">getFillValue</span><span class="o">(</span><span class="n">String</span> <span class="n">defaultValue</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">UUID</span><span class="o">.</span><span class="na">randomUUID</span><span class="o">().</span><span class="na">toString</span><span class="o">();</span> <span class="c1">// 自定义的uuid生成方式</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div></div>
<ul class="task-list">
<li>在application.properties中添加</li>
</ul>
<div class="white"><div class="highlight"><pre># key:填充器全路径类名,value:构造函数参数值,没有可不填
mybatis.fill.com.xx.aa.UUIDFill=
</pre></div></div>
<p>格式为mybatis.fill.类路径=构造参数(没有可不填)</p>
<p>到此已经可以了，当进行insert操作后，id字段会自动插入自定义的uuid。</p>
<p>但是使用过程中还会有个问题，如果数据库中既有自增主键的表，也有自定义UUID主键的表，那么上面的做法就没办法区分了。因此我们要找出自定义UUID主键的表，解决办法是重写FillHandler的match(Class&lt;?&gt; entityClass, Field field, String columnName)方法，完整的代码如下：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UUIDFill</span> <span class="kd">extends</span> <span class="n">FillHandler</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="cm">/* 重写方法，自定义匹配
        entityClass     实体类class
        field           字段信息
        columnName      给定的数据库字段名
    */</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">match</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">entityClass</span><span class="o">,</span> <span class="n">Field</span> <span class="n">field</span><span class="o">,</span> <span class="n">String</span> <span class="n">columnName</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">boolean</span> <span class="n">isPk</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="na">getAnnotation</span><span class="o">(</span><span class="n">Id</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span> <span class="c1">// 是否有@Id注解</span>
        
        <span class="n">GeneratedValue</span> <span class="n">gv</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="na">getAnnotation</span><span class="o">(</span><span class="n">GeneratedValue</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="kt">boolean</span> <span class="n">isAuto</span> <span class="o">=</span> <span class="n">gv</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">gv</span><span class="o">.</span><span class="na">strategy</span><span class="o">()</span> <span class="o">==</span> <span class="n">GenerationType</span><span class="o">.</span><span class="na">AUTO</span><span class="o">;</span> <span class="c1">// 是否有@GeneratedValue注解，并且策略是AUTO</span>
        
        <span class="k">return</span> <span class="n">isPk</span> <span class="o">&amp;&amp;</span> <span class="n">isAuto</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getColumnName</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"id"</span><span class="o">;</span> <span class="c1">// 作用在id字段上</span>
    <span class="o">}</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">FillType</span> <span class="nf">getFillType</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">FillType</span><span class="o">.</span><span class="na">INSERT</span><span class="o">;</span> <span class="c1">// INSERT时触发</span>
    <span class="o">}</span>
    <span class="nd">@Override</span>
    <span class="kd">protected</span> <span class="n">Object</span> <span class="nf">getFillValue</span><span class="o">(</span><span class="n">String</span> <span class="n">defaultValue</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">UUID</span><span class="o">.</span><span class="na">randomUUID</span><span class="o">().</span><span class="na">toString</span><span class="o">();</span> <span class="c1">// 自定义的uuid生成方式</span>
    <span class="o">}</span>

<span class="o">}</span>
</pre></div></div>
<p>这样就能区分出自增主键和自定义主键了。</p>
<p>自定义uuid生成的配置方式采用的是easymybatis提供的字段填充功能，具体说明可参考 <strong>字段自动填充</strong> 小节。</p>
<h1>
<a id="字段自动填充" class="anchor" href="#%E5%AD%97%E6%AE%B5%E8%87%AA%E5%8A%A8%E5%A1%AB%E5%85%85"></a>字段自动填充</h1>
<h2>
<a id="填充器设置" class="anchor" href="#%E5%A1%AB%E5%85%85%E5%99%A8%E8%AE%BE%E7%BD%AE"></a>填充器设置</h2>
<p>假设数据库表里面有两个时间字段gmt_create,gmt_update。</p>
<p>当进行insert操作时gmt_create，gmt_update字段需要更新。当update时，gmt_update字段需要更新。</p>
<p>通常的做法是通过Entity手动设置：</p>
<div class="white"><div class="highlight"><pre><span class="n">User</span> <span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="n">User</span><span class="o">();</span>
<span class="n">user</span><span class="o">.</span><span class="na">setGmtCreate</span><span class="o">(</span><span class="k">new</span> <span class="n">Date</span><span class="o">());</span>
<span class="n">user</span><span class="o">.</span><span class="na">setGmtUpdate</span><span class="o">(</span><span class="k">new</span> <span class="n">Date</span><span class="o">());</span>
</pre></div></div>
<p>因为表设计的时候大部分都有这两个字段，所以对每张表都进行手动设置的话很容易错加、漏加。
easymybatis提供了两个辅助类DateFillInsert和DateFillUpdate，用来处理添加修改时的时间字段自动填充。配置了这两个类之后，时间字段将会自动设置。</p>
<p>springboot项目配置方式如下：</p>
<p>在application.properties中添加</p>
<div class="white"><div class="highlight"><pre>mybatis.fill.net.oschina.durcframework.easymybatis.support.DateFillInsert=
mybatis.fill.net.oschina.durcframework.easymybatis.support.DateFillUpdate=
</pre></div></div>
<p>如果要指定字段名，可以写成：</p>
<div class="white"><div class="highlight"><pre>mybatis.fill.net.oschina.durcframework.easymybatis.support.DateFillInsert=add_time
</pre></div></div>
<p>在springmvc的xml中配置如下:</p>
<div class="white"><div class="highlight"><pre><span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">"sqlSessionFactory"</span>
        <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.ext.SqlSessionFactoryBeanExt"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"dataSource"</span> <span class="na">ref=</span><span class="s">"dataSource"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"configLocation"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;value&gt;</span>classpath:mybatis/mybatisConfig.xml<span class="nt">&lt;/value&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"mapperLocations"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;list&gt;</span>
                <span class="nt">&lt;value&gt;</span>classpath:mybatis/mapper/*.xml<span class="nt">&lt;/value&gt;</span>
            <span class="nt">&lt;/list&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        
        <span class="c">&lt;!-- 以下是附加属性 --&gt;</span>
        
        <span class="c">&lt;!-- dao所在的包名,跟MapperScannerConfigurer的basePackage一致 
            多个用;隔开
        --&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"basePackage"</span> <span class="na">value=</span><span class="s">"com.myapp.dao"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"config"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.EasymybatisConfig"</span><span class="nt">&gt;</span>
                                <span class="c">&lt;!-- 定义填充器 --&gt;</span>
                <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"fills"</span><span class="nt">&gt;</span>
                    <span class="nt">&lt;list&gt;</span>
                                        <span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.support.DateFillInsert"</span><span class="nt">/&gt;</span>
                                        <span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.support.DateFillUpdate"</span><span class="nt">/&gt;</span>
                    <span class="nt">&lt;/list&gt;</span>
                <span class="nt">&lt;/property&gt;</span>
            <span class="nt">&lt;/bean&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
    <span class="nt">&lt;/bean&gt;</span>
</pre></div></div>
<h2>
<a id="自定义填充器" class="anchor" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A1%AB%E5%85%85%E5%99%A8"></a>自定义填充器</h2>
<p>除了使用easymybatis默认提供的填充之外，我们还可以自定义填充。</p>
<p>自定义填充类要继承FillHandler类。
 表示填充字段类型，如Date，String，BigDecimal，Boolean。</p>
<h3>
<a id="实战springboot" class="anchor" href="#%E5%AE%9E%E6%88%98springboot"></a>实战(springboot)</h3>
<p>现在有个remark字段，需要在insert时初始化为“备注默认内容”，新建一个StringRemarkFill类如下：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringRemarkFill</span> <span class="kd">extends</span> <span class="n">FillHandler</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getColumnName</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"remark"</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">FillType</span> <span class="nf">getFillType</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">FillType</span><span class="o">.</span><span class="na">INSERT</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">protected</span> <span class="n">Object</span> <span class="nf">getFillValue</span><span class="o">(</span><span class="n">String</span> <span class="n">defaultValue</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"备注默认内容"</span><span class="o">;</span>
    <span class="o">}</span>

<span class="o">}</span>
</pre></div></div>
<p>StringRemarkFill类中有三个重写方法：</p>
<ul class="task-list">
<li>getColumnName() ： 指定表字段名</li>
<li>getFillType() ： 填充方式，FillType.INSERT:仅insert时填充； FillType.UPDATE：insert，update时填充</li>
<li>getFillValue(String defaultValue) ：返回填充内容</li>
</ul>
<p>然后在application.properties中添加</p>
<div class="white"><div class="highlight"><pre>mybatis.fill.com.xx.StringRemarkFill=
</pre></div></div>
<p>这样就配置完毕了，调用dao.save(user);时会自动填充remark字段。</p>
<h2>
<a id="指定目标类" class="anchor" href="#%E6%8C%87%E5%AE%9A%E7%9B%AE%E6%A0%87%E7%B1%BB"></a>指定目标类</h2>
<p>上面说到StringRemarkFill填充器，它作用在所有实体类上，也就是说实体类如果有remark字段都会自动填充。这样显然是不合理的，解决办法是指定特定的实体类。只要重写FillHandler类的getTargetEntityClasses()方法即可。</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">getTargetEntityClasses</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="o">{</span> <span class="n">TUser</span><span class="o">.</span><span class="na">class</span> <span class="o">};</span>
<span class="o">}</span>
</pre></div></div>
<p>这样就表示作用在TUser类上，多个类可以追加。最终代码如下：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringRemarkFill</span> <span class="kd">extends</span> <span class="n">FillHandler</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getColumnName</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"remark"</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="n">getTargetEntityClasses</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">Class</span><span class="o">&lt;?&gt;[]</span> <span class="o">{</span> <span class="n">TUser</span><span class="o">.</span><span class="na">class</span> <span class="o">};</span> <span class="c1">// 只作用在TUser类上</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">FillType</span> <span class="nf">getFillType</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">FillType</span><span class="o">.</span><span class="na">INSERT</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">protected</span> <span class="n">Object</span> <span class="nf">getFillValue</span><span class="o">(</span><span class="n">String</span> <span class="n">defaultValue</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">"备注默认内容"</span><span class="o">;</span> <span class="c1">// insert时填充的内容</span>
    <span class="o">}</span>

<span class="o">}</span>
</pre></div></div>
<h2>
<a id="高级匹配" class="anchor" href="#%E9%AB%98%E7%BA%A7%E5%8C%B9%E9%85%8D"></a>高级匹配</h2>
<p>覆盖FillHandler类中的match方法可以让填充器做更高级的匹配，match方法如下</p>
<div class="white"><div class="highlight"><pre><span class="cm">/**
 * 是否能够作用到指定字段
 * @param entityClass 实体类class
 * @param field 字段信息
 * @param columnName 给定的数据库字段名
 * @return
 */</span>
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">match</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">entityClass</span><span class="o">,</span> <span class="n">Field</span> <span class="n">field</span><span class="o">,</span> <span class="n">String</span> <span class="n">columnName</span><span class="o">)</span>
</pre></div></div>
<p>这个方法返回的是一个boolean，返回true则代表作用到该属性上。例如下面的代码：</p>
<ul class="task-list">
<li>匹配出含有@Id和@GeneratedValue(strategy=GenerationType.AUTO)的字段</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">match</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">entityClass</span><span class="o">,</span> <span class="n">Field</span> <span class="n">field</span><span class="o">,</span> <span class="n">String</span> <span class="n">columnName</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">boolean</span> <span class="n">isPk</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="na">getAnnotation</span><span class="o">(</span><span class="n">Id</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span> <span class="c1">// 是否有@Id注解</span>
        
        <span class="n">GeneratedValue</span> <span class="n">gv</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="na">getAnnotation</span><span class="o">(</span><span class="n">GeneratedValue</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="kt">boolean</span> <span class="n">isAuto</span> <span class="o">=</span> <span class="n">gv</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">gv</span><span class="o">.</span><span class="na">strategy</span><span class="o">()</span> <span class="o">==</span> <span class="n">GenerationType</span><span class="o">.</span><span class="na">AUTO</span><span class="o">;</span> <span class="c1">// 是否有@GeneratedValue注解，并且策略是AUTO</span>
        
        <span class="k">return</span> <span class="n">isPk</span> <span class="o">&amp;&amp;</span> <span class="n">isAuto</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div></div>
<p>关于自动填充的原理是基于mybatis的TypeHandler实现的，这里就不多做介绍了。感兴趣的同学可以查看FillHandler源码。</p>
<h1>
<a id="entity中使用枚举字段" class="anchor" href="#entity%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%9E%9A%E4%B8%BE%E5%AD%97%E6%AE%B5"></a>Entity中使用枚举字段</h1>
<p>数据库中一些状态字段通常用0,1,2或者简单的字符串进行维护，然后JavaBean实体类中用枚举类型来保存，这样做便于使用和维护。</p>
<p>easymybatis上使用枚举属性很简单：枚举类实现net.oschina.durcframework.easymybatis.handler.BaseEnum接口即可。</p>
<p>下面是具体例子：</p>
<h2>
<a id="第一步" class="anchor" href="#%E7%AC%AC%E4%B8%80%E6%AD%A5"></a>第一步</h2>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">enum</span> <span class="n">UserInfoType</span> <span class="kd">implements</span> <span class="n">BaseEnum</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="n">INVALID</span><span class="o">(</span><span class="s">"0"</span><span class="o">),</span><span class="n">VALID</span><span class="o">(</span><span class="s">"1"</span><span class="o">)</span>
    <span class="o">;</span>

    <span class="kd">private</span> <span class="n">String</span> <span class="n">status</span><span class="o">;</span>

    <span class="n">UserInfoType</span><span class="o">(</span><span class="n">String</span> <span class="n">type</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">status</span> <span class="o">=</span> <span class="n">type</span><span class="o">;</span>
    <span class="o">}</span>
    
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">getCode</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">status</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>

</pre></div></div>
<p>首先定义一个枚举类，实现BaseEnum接口，接口类型参数用String，表示保存的值是String类型，如果要保存Int类型的话改用BaseEnum。</p>
<h2>
<a id="第二步" class="anchor" href="#%E7%AC%AC%E4%BA%8C%E6%AD%A5"></a>第二步</h2>
<p>在javaBean添加该枚举属性：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserInfo</span> <span class="o">{</span>
    <span class="o">...</span>
    <span class="kd">private</span> <span class="n">UserInfoType</span> <span class="n">status</span><span class="o">;</span>

    <span class="c1">// 省略getter setter</span>
<span class="o">}</span>
</pre></div></div>
<p>接下来就可以使用dao来进行数据操作了，下面是完整测试用例：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserInfoDaoTest</span> <span class="kd">extends</span> <span class="n">EasymybatisSpringbootApplicationTests</span> <span class="o">{</span>
    
    <span class="nd">@Autowired</span>
    <span class="n">UserInfoDao</span> <span class="n">userInfoDao</span><span class="o">;</span>
    
    <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testGet</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">UserInfo</span> <span class="n">userInfo</span> <span class="o">=</span> <span class="n">userInfoDao</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="n">print</span><span class="o">(</span><span class="s">"枚举字段status："</span> <span class="o">+</span> <span class="n">userInfo</span><span class="o">.</span><span class="na">getStatus</span><span class="o">().</span><span class="na">getCode</span><span class="o">());</span>
        <span class="n">print</span><span class="o">(</span><span class="n">userInfo</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testUpdate</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">UserInfo</span> <span class="n">userInfo</span> <span class="o">=</span> <span class="n">userInfoDao</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// 修改枚举值</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setStatus</span><span class="o">(</span><span class="n">UserInfoType</span><span class="o">.</span><span class="na">INVALID</span><span class="o">);</span>
        <span class="n">userInfoDao</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">userInfo</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="nd">@Test</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testSave</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">UserInfo</span> <span class="n">userInfo</span> <span class="o">=</span> <span class="k">new</span> <span class="n">UserInfo</span><span class="o">();</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setAddress</span><span class="o">(</span><span class="s">"aa"</span><span class="o">);</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setCity</span><span class="o">(</span><span class="s">"杭州"</span><span class="o">);</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setCreateTime</span><span class="o">(</span><span class="k">new</span> <span class="n">Date</span><span class="o">());</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setUserId</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// 枚举值</span>
        <span class="n">userInfo</span><span class="o">.</span><span class="na">setStatus</span><span class="o">(</span><span class="n">UserInfoType</span><span class="o">.</span><span class="na">VALID</span><span class="o">);</span>
        <span class="n">userInfoDao</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">userInfo</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
 
</pre></div></div>
<h1>
<a id="sql写在xml中" class="anchor" href="#sql%E5%86%99%E5%9C%A8xml%E4%B8%AD"></a>SQL写在xml中</h1>
<p>easymybatis提供的一些查询方式已经满足大部分的查询需求，但是有些复杂的sql语句还是需要写在xml文件中。easymybatis同样支持将sql语句写在xml中，具体配置如下：</p>
<ul class="task-list">
<li>在application.properties添加一句</li>
</ul>
<div class="white"><div class="highlight"><pre>mybatis.mapper-locations=classpath:/mybatis/mapper/*.xml
</pre></div></div>
<p>这句话用来指定xml文件的存放地。</p>
<ul class="task-list">
<li>
<p>在resources目录下新建一个mybatis文件夹，在mybatis文件夹下新建mapper文件夹。
新建一个xml文件，名字跟Dao名字一致，如TUserDao.xml，建完后的文件路径是resources/mybatis/mapper/TUserDao.xml</p>
</li>
<li>
<p>在xml中添加sql语句，如下：</p>
</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="cp">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="cp">&lt;!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"&gt;</span>
<span class="c">&lt;!-- 注意：文件名必须跟Dao类名字一致，因为是根据文件名做关联。 --&gt;</span>
<span class="nt">&lt;mapper&gt;</span>
    
    <span class="nt">&lt;select</span> <span class="na">id=</span><span class="s">"selectByName"</span> <span class="na">parameterType=</span><span class="s">"String"</span> <span class="na">resultMap=</span><span class="s">"baseResultMap"</span><span class="nt">&gt;</span>
        select * from t_user t where t.username = #{username} limit 1
    <span class="nt">&lt;/select&gt;</span>
    
<span class="nt">&lt;/mapper&gt;</span>
</pre></div></div>
<p>这个xml文件跟其它的mybatis配置文件一样，namespace可不写。这里baseResultMap没有看到定义，但是确实存在，因为这个是easymybatis提供的一个内置resultMap。</p>
<ul class="task-list">
<li>在TUseroDao.java中添加：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="n">TUser</span> <span class="nf">selectByName</span><span class="o">(</span><span class="nd">@Param</span><span class="o">(</span><span class="s">"username"</span><span class="o">)</span><span class="n">String</span> <span class="n">username</span><span class="o">);</span>
</pre></div></div>
<ul class="task-list">
<li>编写单元测试用例</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="nd">@Test</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">testSelectByName</span><span class="o">()</span> <span class="o">{</span>
    <span class="n">TUser</span> <span class="n">user</span> <span class="o">=</span> <span class="n">dao</span><span class="o">.</span><span class="na">selectByName</span><span class="o">(</span><span class="s">"张三"</span><span class="o">);</span>

    <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUsername</span><span class="o">());</span>
<span class="o">}</span>
    
</pre></div></div>
<h1>
<a id="配置说明" class="anchor" href="#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E"></a>配置说明</h1>
<p>easymybatis存放一些配置参数，这些参数都有默认值，一般情况下可以不用。如果使用springboot的话可以方便的对参数进行设置，只需在application.properties中设置即可，除此之外还可以设置其他mybatis官方参数，具体可参考<a href="http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/">MyBatis-Spring-Boot-Application configuration parameters</a></p>
<div class="white"><div class="highlight"><pre>mybatis.camel2underline=true
mybatis.common-sql-classpath=
mybatis.mapper-save-dir=
mybatis.mapper-executor-pool-size=50
mybatis.template-classpath=
</pre></div></div>
<p>下面就讲解下各个属性的作用：</p>
<ul class="task-list">
<li>
<p>camel2underline
如果为true，则开启驼峰转换下划线功能。实体类中的java字段映射成数据库字段将自动转成下划线形式。可以省略@Column注解。默认true。</p>
</li>
<li>
<p>mapper-executor-pool-size
mapper处理线程数，此项配置可以加快启动速度。默认值50，生产环境可以设置成较小的数，比如5</p>
</li>
<li>
<p>template-classpath
指定模板文件class路径，开头结尾必须包含"/"。如果没有指定，则默认读取easymybatis/tpl/下的模板，一般情况下不做配置。</p>
</li>
<li>
<p>common-sql-classpath
指定公共SQL模块class路径，如果没有指定，则默认读取easymybatis/commonSql.xml，一般情况下不做配置。</p>
</li>
<li>
<p>mapper-save-dir
指定mapper文件存放路径。因为easymybatis是直接将mapper内容注入到内存当中，开发人员无感知，并且不知道mapper内容是什么样子，这个功能就是让开发人员能够查看到对应的mapper内容，方便定位和排查问题。一般情况下此项不用开启。</p>
</li>
</ul>
<h1>
<a id="其他功能" class="anchor" href="#%E5%85%B6%E4%BB%96%E5%8A%9F%E8%83%BD"></a>其他功能</h1>
<h2>
<a id="指定外部模板" class="anchor" href="#%E6%8C%87%E5%AE%9A%E5%A4%96%E9%83%A8%E6%A8%A1%E6%9D%BF"></a>指定外部模板</h2>
<p>easymybatis依赖模板文件来生成mapper，默认的模板存放在easymybatis/tpl/下，模板文件名对应某一种数据库，如mysql.vm对应mysql数据库。</p>
<p>我们可以通过更改template-classpath的值来改变模板读取的位置。默认template-classpath的值为/easymybatis/tpl/。假如你想对mysql.vm做一些修改，那么可以按照如下步骤进行：</p>
<ol class="task-list">
<li>使用解压工具解压easymybatis.jar</li>
<li>在easymybatis/tpl/下找到mysql.vm，拷贝一份出来，放到你的项目中的classpath下（src/main/resources）</li>
<li>在application.properties中添加一行</li>
</ol>
<div class="white"><div class="highlight"><pre>mybatis.template-classpath=/ 
</pre></div></div>
<p>这样在启动时会自动读取classpath根目录下的mysql.vm。控制台也会打印读取模板的信息：</p>
<div class="white"><div class="highlight"><pre>2017-12-26 19:32:31.021  INFO 13476 --- [           main] n.o.d.e.ext.MapperLocationsBuilder       : 使用模板:/mysql.vm
</pre></div></div>
<p>如果你的项目是springmvc，采用xml配置形式，前两步不变，第三步改为：</p>
<div class="white"><div class="highlight"><pre><span class="c">&lt;!-- 替换org.mybatis.spring.SqlSessionFactoryBean --&gt;</span>
    <span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">"sqlSessionFactory"</span>
        <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.ext.SqlSessionFactoryBeanExt"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"dataSource"</span> <span class="na">ref=</span><span class="s">"dataSource"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"configLocation"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;value&gt;</span>classpath:mybatis/mybatisConfig.xml<span class="nt">&lt;/value&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"mapperLocations"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;list&gt;</span>
                <span class="nt">&lt;value&gt;</span>classpath:mybatis/mapper/*.xml<span class="nt">&lt;/value&gt;</span>
            <span class="nt">&lt;/list&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        
        <span class="c">&lt;!-- 以下是附加属性 --&gt;</span>
        
        <span class="c">&lt;!-- dao所在的包名,跟MapperScannerConfigurer的basePackage一致 
            多个用;隔开
        --&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"basePackage"</span> <span class="na">value=</span><span class="s">"com.myapp.dao"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"config"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.EasymybatisConfig"</span><span class="nt">&gt;</span>
                <span class="c">&lt;!-- 指定外部模板 --&gt;</span>
                <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"templateClasspath"</span> <span class="na">value=</span><span class="s">"/"</span><span class="nt">/&gt;</span>
            <span class="nt">&lt;/bean&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
    <span class="nt">&lt;/bean&gt;</span>
</pre></div></div>
<h2>
<a id="全局dao" class="anchor" href="#%E5%85%A8%E5%B1%80dao"></a>全局Dao</h2>
<p>easymybatis提供了全局Dao支持。</p>
<p>easymybatis设置全局Dao的方式如下：</p>
<ol class="task-list">
<li>在resources下新建一个base.vm内容如下</li>
</ol>
<div class="white"><div class="highlight"><pre><span class="nt">&lt;select</span> <span class="na">id=</span><span class="s">"getMySqlVersion"</span> <span class="na">resultType=</span><span class="s">"String"</span><span class="nt">&gt;</span>
    select version()
<span class="nt">&lt;/select&gt;</span>
</pre></div></div>
<p>获取数据库版本号SQL.</p>
<ol class="task-list">
<li>在application.properties新增一行</li>
</ol>
<div class="white"><div class="highlight"><pre>mybatis.global-vm-location=/base.vm
</pre></div></div>
<p>用来指定文件位置，支持file:，classpath:方式。</p>
<ol class="task-list">
<li>新建一个全局Dao：GlobalDao.java</li>
</ol>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">GlobalDao</span> <span class="o">{</span>
    <span class="n">String</span> <span class="nf">getMySqlVersion</span><span class="o">();</span>
<span class="o">}</span>
</pre></div></div>
<ol class="task-list">
<li>自定义的Dao继承GlobalDao.java</li>
</ol>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">AddressDao</span> <span class="kd">extends</span> <span class="n">CrudDao</span><span class="o">&lt;</span><span class="n">Address</span><span class="o">&gt;,</span><span class="n">GlobalDao</span> <span class="o">{</span>

<span class="o">}</span>
</pre></div></div>
<p>这样AddressDao就具备了getMySqlVersion()功能。base.vm中的文件编写可参考<strong>velocity变量说明</strong></p>
<h2>
<a id="乐观锁" class="anchor" href="#%E4%B9%90%E8%A7%82%E9%94%81"></a>乐观锁</h2>
<p>easymybatis提供的乐观锁使用方式跟JPA一样，使用@Version注解来实现。即：数据库增加一个int或long类型字段version，然后实体类version字段上加上@Version注解即可。实现原理是根据mysql的行锁机制(InnoDB下)，同一条记录只能被一条SQL执行，后面的SQL排队等待。这样version改变后，等待中的SQL还是老的version号，因此更新失败。</p>
<div class="white"><div class="highlight"><pre><span class="nd">@Version</span>  
<span class="kd">private</span> <span class="n">Long</span> <span class="n">version</span><span class="o">;</span>  
</pre></div></div>
<ul class="task-list">
<li>注：更新不成功不会抛出异常，而是update返回值为0</li>
</ul>
<h2>
<a id="逻辑删除" class="anchor" href="#%E9%80%BB%E8%BE%91%E5%88%A0%E9%99%A4"></a>逻辑删除</h2>
<p>从1.7版本开始支持逻辑删除功能,即更新一个字段标记为已删除。查询的时候会自动过滤掉已删除的数据。</p>
<p>假设数据库表中有一个字段is_deleted类型为tinyint，0表示未删除，1表示已删除。</p>
<p>实体类对应代码如下：</p>
<div class="white"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">User</span> <span class="o">{</span>
    <span class="nd">@LogicDelete</span>
    <span class="kd">private</span> <span class="n">Byte</span> <span class="n">isDeleted</span><span class="o">;</span>
<span class="o">}</span>
</pre></div></div>
<p>在执行dao.del(user);时会触发UPDATE语句，将is_deleted字段更新为1。</p>
<p>如果is_deleted类型为char(1)，f表示未删除，t表示已删除。</p>
<div class="white"><div class="highlight"><pre><span class="nd">@LogicDelete</span><span class="o">(</span><span class="n">notDeleteValue</span> <span class="o">=</span> <span class="s">"f"</span><span class="o">,</span> <span class="n">deleteValue</span> <span class="o">=</span> <span class="s">"t"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">isDeleted</span><span class="o">;</span>
</pre></div></div>
<p>@LogicDelete提供两个属性</p>
<ul class="task-list">
<li>notDeleteValue：指定未删除时的值,不指定默认为0</li>
<li>deleteValue：指定删除后保存的值,不指定默认为1</li>
</ul>
<p>假设1表示未删除，2表示已删除，@LogicDelete的设置方法如下：@LogicDelete(notDeleteValue = "1", deleteValue = "2")。如果每个实体类都要这样设置的话会很麻烦，easymybatis提供了全局配置</p>
<ul class="task-list">
<li>springboot下，application.properties添加</li>
</ul>
<div class="white"><div class="highlight"><pre># 未删除数据库保存的值，默认为0
mybatis.logic-not-delete-value=1
# 删除后数据库保存的值，默认为1
mybatis.logic-delete-value=2
</pre></div></div>
<ul class="task-list">
<li>springmvc设置方式如下：</li>
</ul>
<div class="white"><div class="highlight"><pre><span class="c">&lt;!-- 替换org.mybatis.spring.SqlSessionFactoryBean --&gt;</span>
    <span class="nt">&lt;bean</span> <span class="na">id=</span><span class="s">"sqlSessionFactory"</span>
        <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.ext.SqlSessionFactoryBeanExt"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"dataSource"</span> <span class="na">ref=</span><span class="s">"dataSource"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"configLocation"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;value&gt;</span>classpath:mybatis/mybatisConfig.xml<span class="nt">&lt;/value&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"mapperLocations"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;list&gt;</span>
                <span class="nt">&lt;value&gt;</span>classpath:mybatis/mapper/*.xml<span class="nt">&lt;/value&gt;</span>
            <span class="nt">&lt;/list&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
        
        <span class="c">&lt;!-- 以下是附加属性 --&gt;</span>
        
        <span class="c">&lt;!-- dao所在的包名,跟MapperScannerConfigurer的basePackage一致 
            多个用;隔开
        --&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"basePackage"</span> <span class="na">value=</span><span class="s">"com.myapp.dao"</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"config"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;bean</span> <span class="na">class=</span><span class="s">"net.oschina.durcframework.easymybatis.EasymybatisConfig"</span><span class="nt">&gt;</span>     
                <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"logicNotDeleteValue"</span> <span class="na">value=</span><span class="s">"1"</span><span class="nt">/&gt;</span>
                                <span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">"logicDeleteValue"</span> <span class="na">value=</span><span class="s">"2"</span><span class="nt">/&gt;</span>
            <span class="nt">&lt;/bean&gt;</span>
        <span class="nt">&lt;/property&gt;</span>
    <span class="nt">&lt;/bean&gt;</span>
</pre></div></div>
<ul class="task-list">
<li>注：如果同时设置了@LogicDelete参数和全局配置，会优先读取注解中的配置。</li>
</ul>
<h1>
<a id="附录velocity变量说明" class="anchor" href="#%E9%99%84%E5%BD%95velocity%E5%8F%98%E9%87%8F%E8%AF%B4%E6%98%8E"></a>[附录]velocity变量说明</h1>
<h2>
<a id="context" class="anchor" href="#context"></a>${context}</h2>
<ul class="task-list">
<li>${context.dbName} : 数据库名称</li>
<li>${context.packageName} : 包名</li>
<li>${context.javaBeanName} : Java类名</li>
<li>${context.javaBeanNameLF} : Java类名且首字母小写</li>
</ul>
<h2>
<a id="pk" class="anchor" href="#pk"></a>${pk}</h2>
<ul class="task-list">
<li>${pk.isIdentity} : 是否自增</li>
<li>${pk.javaFieldName} ： 主键java字段名</li>
<li>${pk.columnName} ： 主键数据库字段名</li>
<li>${pk.isUuid} ： 主键是否使用UUID策略</li>
</ul>
<h2>
<a id="table" class="anchor" href="#table"></a>${table}</h2>
<ul class="task-list">
<li>${table.tableName} : 数据库表名</li>
<li>${table.comment} : 表注释</li>
<li>${table.javaBeanNameLF} : java类名，并且首字母小写</li>
</ul>
<h2>
<a id="foreachcolumn-in-columnsend" class="anchor" href="#foreachcolumn-in-columnsend"></a>#foreach($column in $columns)...#end</h2>
<ul class="task-list">
<li>${column.columnName} : 表中字段名</li>
<li>${column.type} : java字段类型，String，Integer</li>
<li>${column.fullType} : java字段完整类型，java.lang.String</li>
<li>${column.javaFieldName} : java字段名</li>
<li>${column.javaFieldNameUF} : java字段名首字母大写</li>
<li>${column.javaType} : 字段的java类型</li>
<li>${column.javaTypeBox} : 字段的java装箱类型,如Integer,Long</li>
<li>${column.isIdentity} : 是否自增,返回boolean</li>
<li>${column.isPk} : 是否自增主键,返回boolean</li>
<li>${column.isIdentityPk} : 是否自增主键,返回boolean</li>
<li>${column.isEnum} : 是否枚举类型,返回boolean</li>
<li>${column.mybatisJdbcType} : 返回mybatis定义的jdbcType</li>
<li>${column.comment} : 表字段注释</li>
</ul></div>
          </div>
        </div>
      </div>
      </div>
  </div>
<!-- ***********************************************************内容分割线****************************************************************** -->

                </article>
            </div>
        </div>
    <script src="./static/jquery-1.10.2.min.js"></script>
    <script src="./static/jquery.ztree.all-3.5.min.js"></script>
    <script src="./static/jquery.ztree_toc.min.js"></script>
    <script type="text/javascript">
    var title = document.title;
        $(document).ready(function(){
            $('#tree').ztree_toc({
            	_header_nodes: [{ id:1, pId:0, name:title,open:false}],  // 第一个节点
            	ztreeSetting: {
            		view: {
        				dblClickExpand: false,
        				showLine: true,
        				showIcon: false,
        				selectedMulti: false
        			},
        			data: {
        				simpleData: {
        					enable: true,
        					idKey : "id",
        					pIdKey: "pId"
        					// rootPId: "0"
        				}
        			},
            		callback: {
        				beforeClick: function(treeId, treeNode) {
        					$('a').removeClass('curSelectedNode');
        					if(treeNode.id == 1){
        						$('body').scrollTop(0);
        					}
        					if($.fn.ztree_toc.defaults.is_highlight_selected_line == true) {
        						$('#' + treeNode.id).css('color' ,'red').fadeOut("slow" ,function() {
        							$(this).show().css('color','black');
        						});
        					}
        				}
        			}            		
            	},
                is_auto_number:true, // 菜单是否显示编号，如果markdown标题没有数字标号可以设为true
                documment_selector:'.markdown-body',
                is_expand_all: true // 菜单全部展开
            });
            // 代码高亮
            $('.highlight').each(function(i, block) {
          	    hljs.highlightBlock(block);
          	});
        });
    </script>
    </body>
</html>